package com.a.lib_utils

import com.blankj.utilcode.util.LogUtils
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.lang.reflect.TypeVariable
import java.lang.reflect.WildcardType

object ClassUtil {


    /**
     * 根据类获取对象, 不再必须一个无参构造
     * @param clazz [Class]
     * @param <T>   泛型
     * @return 初始化后的对象
    </T> */
    fun <T> newInstance(clazz: Class<T>?): T? {
        if (clazz == null) return null
        try {
            val cons = clazz.declaredConstructors
//            for (c in cons) {
            val c = cons[0]
            val cls = c.parameterTypes
            return if (cls.isEmpty()) {
                c.isAccessible = true
                c.newInstance() as T
            } else {
                val objects = arrayOfNulls<Any>(cls.size)
                for (i in cls.indices) {
                    objects[i] = getDefaultPrimitiveValue(cls[i])
                }
                c.isAccessible = true
                c.newInstance(*objects) as T
            }
//            }
        } catch (e: java.lang.Exception) {
            LogUtils.e(e.toString())
        }
        return null
    }

    /**
     * 获取 Class 原始类型值
     * @param clazz [Class]
     * @return 原始类型值
     */
    fun getDefaultPrimitiveValue(clazz: Class<*>?): Any? {
        return if (clazz != null && clazz.isPrimitive) {
            if (clazz == Boolean::class.javaPrimitiveType) false else 0
        } else null
    }

    /**
     * 判断 Class 是否为原始类型
     * @param clazz [Class]
     * @return `true` yes, `false` no
     */
    fun isPrimitive(clazz: Class<*>?): Boolean {
        return clazz != null && clazz.isPrimitive
    }

    /**
     * 获取父类泛型类型
     * @param clazz [Class]
     * @param pos   泛型参数索引
     * @return 泛型类型
     */
    fun getGenericSuperclass(
        clazz: Class<*>?,
        pos: Int
    ): Type? {
        if (clazz != null && pos >= 0) {
            try {
                return (clazz.genericSuperclass as ParameterizedType)
                    .actualTypeArguments[pos]
            } catch (e: Exception) {
                LogUtils.e(e.toString())
            }
        }
        return null
    }


    /**
     * 获取 Type Class
     * @param type [Type]
     * @return Type Class
     */
    fun getClass(type: Type?): Class<*>? {
        if (type == null) return null
        try {
            if (type.javaClass == Class::class.java) {
                return type as Class<*>?
            }
            if (type is ParameterizedType) {
                return getClass(type.rawType)
            }
            if (type is TypeVariable<*>) {
                val boundType = type.bounds[0]
                return boundType as Class<*>
            }
            if (type is WildcardType) {
                val upperBounds = type.upperBounds
                if (upperBounds.size == 1) {
                    return getClass(upperBounds[0])
                }
            }
        } catch (e: java.lang.Exception) {
            LogUtils.e(e.toString())
        }
        return Any::class.java
    }

}